<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
			var nameT = "cd";
			this.nameT = "ab";
			(function() {
				console.log(this.nameT, 1)
			}())

			const exte = [{
					a: "a"
				},
				{
					a: "a"
				}
			]
			console.log(...exte, "exte")
			const exte2 = [
				...exte,
				{
					b: "b",
					...exte
				}
			]
			console.log(exte2, "exte2")

			function sum([a, b, c]) {
				// "use strict"
				// console.log(this, "testThis")
				let sum = a + b + c
				console.log(a, b, c, "single")
				console.log(sum, "sum")
				return sum
			}
			window.sum([1, 2, 3])

			var total = 0

			function tSum(a, ...num) {
				if (a !== undefined) {
					console.log(a, "a")
					tSum(...num)
					total += a
				}
				return total
			}
			console.log(tSum(1, 2, 3), "tSum")

			function tSum2(a, ...num) {
				// debugger
				// console.log(num, "num")
				if (num[0]) {
					console.log(a, "num[sum]")
					return a + tSum2(...num)
				} else {
					console.log(a, "num[a]")
					return a
				}
				// return num[0] ? a + tSum2(...num) : a
			}
			console.log(tSum2(5, 2, 3), "tSum2")

			function tSum3(...data) {
				let sum = 0
				for (let val of data) {
					sum += val
				}
				return sum
			}
			console.log(tSum3(1, 2, 3), 'tSum3')

			const arrSum = [1, 2, 3]
			Array.prototype.sum = function() {
				return this.reduce((prev, next) => {
					console.log(prev, next)
					return prev + next
				}, 3)
			}
			console.log(arrSum.sum(), "arrSum")

			const arrMax = [1, 2, 3]
			Array.prototype.Max = function(num) {
				let nums = [...this, num]
				console.log(nums, "maxThis")
				return Math.max(...nums)
			}
			console.log(arrMax.Max(5), "max")

			var count = {
				price: 10
			}

			function fn1(obj, a) { // 纯函数
				return obj.price + a
			}
			console.log(count, "count")
			fn1(count, 5)

			function fn2(obj, a) { // 非纯函数
				obj.price = 50
				return obj.price + a
			}
			fn2(count, 5)
			console.log(count, "count2")

			const fn = function(name = "fn1", age = 18) {
				this.name = name
				this.age = age
				console.log(this, "this")
				this.fn2 = () => {
					this.name = "fn2"
					var name = "name"
					return this.name
				}
			}
			console.log(new fn().fn2(), "fn1")

			const objThis = {
				name: "name1",
				skill: () => {
					// this.name = "skillname"
					// console.log(this, "thisskill")
					console.log(this.name, "objThis") // undefined
				},
				obj2: {
					name: "name2",
					skill: function() {
						// console.log(this, "thisskill2")
						this.name = "skillname"
						console.log(this.name, "objThis2") // skillname
					}
				}
			}
			objThis.skill()
			objThis.obj2.skill()

			var str = "s t r"
			console.log(str[2], "str")

			var strs = "The full name of China is the People's Republic of China.";
			var strsI = strs.indexOf(" The");
			if (strsI) {
				console.log(strsI)
			} else {
				console.log(1)
			}

			const setData = new Set(["red", "green"])
			for (let item of setData.values()) {
				console.log(item, "SetItem")
			}

			// https://www.cnblogs.com/miangao/p/17438480.html
			// JS 中 for in 和 for of 的区别 
			{
				const arr1 = ['Eula', 'Umbra', 'Kaya']
				for (let i in arr1) {
					console.log(i, 'for-in') // '0', '1', '2'
				}
				// 对比
				for (let i of arr1) {
					console.log(i, 'for-of') // Eula, Umbra, Kaya
				}
			}

			{
				const arr1 = ['Eula', 'Umbra', 'Kaya'];
				console.log(arr1, 'arr1.__proto__');
				//下面两种在原型上添加属性的效果是一样的
				Array.prototype.UmbraName = '安柏';
				arr1.__proto__.constructor.prototype.EulaName = '尤菈';
				arr1.__proto__.constructor.prototype.sayHello = function() {
					return 'hello';
				};
				for (let i in arr1) {
					console.log(i + ':' + arr1[i], 'for-in-arr');
				}

				/*
				打印结果：
				0: Eula
				1: Umbra
				2: Kaya
				UmbraName: 安柏
				EulaName: 尤菈
				sayHello: function() {
					return 'hello';
				}
				*/
			}

			{
				const obj = {
					name: 'Eula',
					friend: 'Umbra',
					age: 18,
				};
				obj.__proto__.constructor.prototype.EulaName = '尤菈-劳伦斯';
				Object.prototype.UmbraName = '安柏';
				for (let key in obj) {
					console.log(key + ':' + obj[key], 'for-in-obj');
				}

				/*
				打印结果：
				name: Eula
				friend: Umbra
				age: 18
				EulaName: 尤菈 - 劳伦斯
				UmbraName: 安柏
				*/
			}

			// [{
			// 		"value": 1
			// 	},
			// 	{
			// 		"value": 2
			// 	},
			// 	{
			// 		"value": 3
			// 	}
			// ] // set
			const set = new Set([1, 1, 2, 3])
			const arrSet = Array.from(set)
			console.log(set, [...set], arrSet, Object.entries(set), "set")

			const obj = {
				name: "ab",
				age: 18
			}
			// [
			// 	[
			// 		"name",
			// 		"ab"
			// 	],
			// 	[
			// 		"age",
			// 		18
			// 	]
			// ] // entries
			const map = new Map(Object.entries(obj))
			console.log(Object.entries(obj), "entries")
			// [{
			// 	"key": "name",
			// 	"value": "ab"
			// }, {
			// 	"key": "age",
			// 	"value": 18
			// }] // map
			console.log(map, "map")
			// map.clear()
			console.log(map.get("age"), map.size, "mapSize")

			// [{
			// 	"key": "h",
			// 	"value": "hello"
			// }, {
			// 	"key": "w",
			// 	"value": "world"
			// }] // hw
			const hw = new Map()
			hw.set("h", "hello")
			hw.set("w", "world")
			console.log(hw, "hw")

			{
				name = 'name'
				let sayName = function() {
					console.log(this.name, 'name'); // name
				}
				sayName()
			} {
				name = 'name2'
				let sayName = () => {
					console.log(this.name, 'name2'); // name2
				}
				sayName()
			} {
				name = 'name3'
				var obj1 = {
					name: 'tom',
					sayName: function() {
						console.log(this.name, 'name3'); // tom
						const fn = function() {
							console.log(this.name, 'name3fn'); // name3
						}
						fn()
						// const fn2 = function() {
						// 	console.log(this.name, 'name3'); // name3
						// }
						const fn2 = () => {
							console.log(this.name, 'name3'); // tom
						}
						return fn2
					}
				}
				obj1.sayName()()
				// let abc  = obj1.sayName
				// abc()()
			} {
				name = 'name4'
				var obj1 = {
					name: 'tom',
					sayName: () => {
						console.log(this.name, 'name4'); // name4
						return () => {
							console.log(this.name, 'name4'); // name4
						}
					}
				}
				obj1.sayName()()
			} {
				var objsay = {
					say: function() {
						// setTimeout(function() {
						// 	console.log(this, 'setTimeout')
						// })
						// setTimeout(() => {
						// 	console.log(this, 'setTimeout')
						// })
						// var f1 = function() {
						// 	console.log(this, 'objsayf1') // window
						// 	setTimeout(() => {
						// 		console.log(this) // window
						// 	})
						// }
						var f1 = () => {
							console.log(this, 'objsayf1') // objsay
							setTimeout(() => {
								// console.log(this) // objsay
							})
						}
						f1()
					}
				}
				objsay.say(); // obj
			} {
				// 1
				var x = 1;
				const obj = {
					x: 2,
					say: () => {
						console.log(this); // window
						console.log(this.x); // 1
					}
				}
				obj.say();

				// 2
				var a = 3;

				function test() {
					this.a = 4;
					var fn = () => {
						console.log(this); // test
						console.log(this.a) // 4
					}
					fn();
				}
				var x = new test();

				// 3
				var b = 5;

				function test2() {
					this.b = 6;
					let func = () => {
						console.log(this); // window
						console.log(this.b) // 6
					}
					func();
				}
				test2();
			} {
				function foo() {
					console.log(this, 'foo') // obj1
				}
				const obj1 = {
					foo,
					ab: 1
				}
				const obj2 = {
					obj1
				}
				obj2.obj1.foo()
			} {
				const arr = [1]
				arr.filter(function() {
					console.log(this, 'filter')
				}, {
					a: 1
				})
				arr.filter(() => {
					console.log(this, 'filter')
				})
			}

			{
				age = 16
				const obj = {
					namme: 'obj',
					age: 18,
					fn() {
						age: 21
						console.log(this.age, 'fn') // 18
					},
					fnN: () => {
						age: 23
						console.log(this.age, 'fnN') // 16
						return () => {
							console.log(this.age, 'fnN2') // 16
						}
					},
					obj2: {
						name: 'obj2',
						age: 25,
						fn() {
							age: 29
							console.log(this.age, 'obj2fn') // 25
							return () => {
								age: 31
								console.log(this.age, 'obj2fn2') // 25
								return () => {
									console.log(this.age, 'obj2fn3') // 25
								}
							}
						},
						fnN: () => {
							age: 31
							console.log(this.age, 'obj2fnN') // 16
							return () => {
								console.log(this.age, 'obj2fnN2') // 16
							}
						}
					}
				}
				obj.fn()
				obj.fnN()()
				obj.obj2.fn()()()
				obj.obj2.fnN()()
			}

			{
				let show = () => {
					console.log(this, '=>')
				}
				const obj = {
					show: show
				}
				console.log(show(), 'show')
				console.log(obj.show(), 'show2')
			}

			{
				function foo() {
					setTimeout(() => {
						console.log(this.id, 'id')
					}, 100)
				}
				var id = 21
				// foo()
				foo.call({
					id: 41
				})
			}

			{
				function foo() {
					return () => {
						return () => {
							return () => {
								console.log(this.id, 'idfn')
							}
						}
					}
				}
				var f = foo.call({
					id: 1
				})
				var f1 = f.call({
					id: 2
				})()()
				var f2 = f().call({
					id: 3
				})()
				var f3 = f()().call({
					id: 4
				})
			}

			{
				function Timer() {
					this.s1 = 0
					this.s2 = 0
					setInterval(() => this.s1++, 1000)
					setInterval(function() {
						this.s2++
					}, 1000)
				}
				var timer = new Timer()
				setTimeout(() => console.log(timer.s1, 's1'), 3100) // 3
				setTimeout(() => console.log(timer.s2, 's2'), 3100) // 0
			}
		</script>
	</body>
</html>